package com.pzr.soccer.crawler.aop;
import com.pzr.soccer.crawler.model.CrawlerContext;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Objects;

@Component
@Aspect
@Slf4j
public class RecordExceptionAspect {
    @Autowired
    MongoOperations mongoOperations;


    @Around("@annotation(EnableRecordError)")
    public Object scanError(ProceedingJoinPoint pj) throws Exception {
        MethodSignature signature = (MethodSignature) pj.getSignature();
        Method method = signature.getMethod();
        LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
        String[] parameterNames = discoverer.getParameterNames(method);
        Object[] args = pj.getArgs();
        ErrorRecord errorRecord = new ErrorRecord();
        CrawlerContext context = new CrawlerContext();
        for (int i = 0; i < Objects.requireNonNull(parameterNames).length; i++) {
            if ("context".equals(parameterNames[i])) {
                context = (CrawlerContext) args[i];
                errorRecord.setTag(context.getTag());
                errorRecord.setUrl(context.getUrl());
            }
        }

        if(!errorRecord.getUrl().isBlank()){
            mongoOperations.save(errorRecord);
        }


        //抛出错误让controllerAdvice处理
        if (context.getParseErrors() > ErrorRecord.Errors_Limit || context.getExtractErrors() > ErrorRecord.Errors_Limit) {
            throw new Exception("too_many_errors_in_crawler_task:"+Math.max(context.getExtractErrors(), context.getParseErrors()));
        } else {
            try {
                return pj.proceed();
            } catch (Throwable e) {
                log.error("in aspect:" + e.getMessage());
                return e;
            }
        }
    }

}
